// 引入依赖模块
const WebSocket = require('ws');
const http = require('http');

// 引入连接池功能
const {
    addConnection,
    removeConnection,
    getAllConnections,
    broadcastMessage,
    sendMessageTo,
    getAllClientIds,
    getClientNameById, getConnectionById
} = require('./WebSocketPool');

// 创建 HTTP 服务器（仅用于承载 WebSocket）
const server = http.createServer((req, res) => {
    res.writeHead(400);
    res.end('Bad Request');
});

/**
 * 获取当前在线用户列表
 * @returns {Array<{id: string, name: string}>}
 */
function getOnlineUsersList() {
    return getAllConnections().map(conn => ({
        id: conn.id,
        name: conn.name
    }));
}


/**
 * 广播用户状态信息（上线/下线）
 * @param {string} content - 描述内容，如 "张三 上线了"
 * @param {Array<{id: string, name: string}>} onlineUsers - 当前在线用户列表
 */
function broadcastPresence(content, onlineUsers) {
    // console.log('广播用户状态信息（上线/下线）')
    const message = JSON.stringify({
        type: 'presence',
        content,
        onlineUsers
    });

    // 向所有在线客户端广播消息
    getAllConnections().forEach(({ws}) => {
        if (ws.readyState === WebSocket.OPEN) {
            ws.send(message);
        }
    });
}

/**
 * 格式化消息内容，确保 content 是字符串
 * @param {*} content - 原始的消息内容（可能是 string 或 object）
 * @returns {string} 处理后的字符串内容
 */
function formatMessageContent(content) {
    if (typeof content === 'object' && !Array.isArray(content) && content !== null) {
        return JSON.stringify(content); // 对象转为字符串
    }
    return String(content); // 确保其他类型也转换为字符串
}

/**
 * 设置单个客户端的连接逻辑
 * @param {WebSocket} ws - 客户端 WebSocket 连接对象
 */
function setupClientConnection(ws) {
    let clientId;     // 用户唯一 ID
    let clientName;   // 用户昵称

    // ❤️ 心跳检测定时器：每 30 秒发送一次 ping
    const heartbeatInterval = setInterval(() => {
        if (ws.isAlive === false) {
            // 添加下线广播
            // if (clientName) {
            //     const onlineUsers = getOnlineUsersList();
            //     broadcastPresence(`${clientName} 突然-下线了`, onlineUsers);
            // }
            // console.log(`Client ${clientId} did not respond to ping, terminating...`);
            ws.terminate();       // 主动关闭无响应连接
            clearInterval(heartbeatInterval); // 清除定时器
            return;
        }
        ws.isAlive = false; // 等待 pong 响应
        ws.ping();          // 发送心跳包
    }, 3000);

    // 收到 pong 响应后标记为活跃
    ws.on('pong', () => {
        ws.isAlive = true;
    });

    // 处理客户端第一次发来的注册消息
    ws.once('message', (rawMessage) => {
        try {
            // console.log('处理客户端第一次发来的注册消息', rawMessage)
            const messageData = JSON.parse(rawMessage);
            // console.log('messageData', messageData)

            // 检查是否是合法的注册消息
            if (messageData.type === 'register' && messageData.name) {
                const context = {name: messageData.name};
                const connectionInfo = addConnection(ws, context);
                // console.log('添加连接信息', connectionInfo)
                clientId = connectionInfo.id;
                clientName = connectionInfo.name;

                const onlineUsers = getOnlineUsersList();
                // console.log('发送连接成功消息和在线用户列表', onlineUsers)
                // 发送连接成功消息和在线用户列表
                ws.send(JSON.stringify({
                    type: 'connected',
                    clientId,
                    clientName,
                    onlineClients: onlineUsers
                }));
                // 广播上线通知
                // console.log('广播上线通知')
                broadcastPresence(`${clientName} 上线了`, onlineUsers);
            } else {
                // 注册失败，关闭连接
                ws.send(JSON.stringify({type: 'error', content: '必须先注册昵称'}));
                ws.close();
            }
        } catch (e) {
            console.error('Error parsing register message:', e);
            ws.send(JSON.stringify({type: 'error', content: '注册失败，请重试'}));
            ws.close();
        }
    });

    // 处理后续的消息（私聊或群发）
    ws.on('message', (rawMessage) => {
        try {
            const messageData = JSON.parse(rawMessage);
            const {to, content} = messageData;
            const formattedContent = formatMessageContent(content);
            let palyload
            if (messageData.type === 'private') {
                palyload = JSON.stringify({
                    type: 'private',
                    from: clientId,
                    fromName: clientName,
                    content: formattedContent
                })
                sendMessageTo(to, palyload);
            } else if (messageData.type === 'servo_control') {
                // 否则，发送带元信息的私聊消息
                console.log('formattedContent',to,JSON.parse(formattedContent),  typeof (formattedContent))
                palyload = JSON.stringify({
                    type: 'servo_control',
                    content: formattedContent
                })
                sendMessageTo(to, palyload);
            } else if (messageData.type === 'broadcast') { // 广播
                palyload = JSON.stringify({
                    type: 'broadcast',
                    from: clientId,
                    fromName: clientName,
                    content: formattedContent
                })
                broadcastMessage(palyload);
            }
        } catch (e) {
            // console.error('Error parsing message:', e);
            ws.send(JSON.stringify({type: 'error', content: '消息格式错误'}));
        }
    });

    // 客户端断开连接时处理
    ws.on('close', () => {
        if (clientName) {
            const onlineUsers = getOnlineUsersList();
            broadcastPresence(`${clientName} 下线了`, onlineUsers);
        }

        clearInterval(heartbeatInterval); // 清除心跳定时器
        removeConnection(ws);            // 从连接池中移除该连接
    });
}

// 初始化 WebSocket 服务
const wss = new WebSocket.Server({server});

// 监听新连接事件
wss.on('connection', (ws) => {
    // console.log('New WebSocket client connected');
    setupClientConnection(ws);
});

/**
 * 启动 HTTP 和 WebSocket 服务
 * @param {number} port - 要监听的端口号
 */
function start(port) {
    if (typeof port !== 'number' || isNaN(port) || port < 0 || port >= 65536) {
        console.error(`Invalid port: ${port}. Using default port 9102`);
        port = 9102;
    }

    server.listen(port, '0.0.0.0', () => {
        console.log(`WebSocket 已启动!端口: ${port}`);
    });
}

// 显式导出启动函数
module.exports = {start};
